/**
 * 摄像头组件
 * 版本：1.0.0
 * 日期：2018/6/1
 * 日志：
 *  1. v1.0.0 2018/6/1 创建
 *  2. v1.0.1 2018/11/20 修改弹窗的样式
 */
layui.define(['jquery', 'layer', 'view'], function(e) {
  // 运用了webCam组件
  // /////////////////////////////////////////
  var
    $ = layui.jquery;
  var ly = layui.layer;
  var vw = layui.view;
  var
    defaultName = 'img_' + new Date().getTime();
  var defaultSuffix = '.png';

  var camera = { v: '1.0.0' };

  function isValidName(name) {
    if (!name) return false;
    return /^(?!\.)[^\\\/:\*\?"<>\|]{1,255}$/.test(name);
  }

  function isEmptyObject(obj) {
    for (var k in obj) {
      return false;
    }
    return true;
  }

  function setCss() {
    if (document.querySelector('#camera__style')) return;
    // 组装样式
    var styleNode = document.createElement('style');
    var cssString = '' +
      '.camera__center{text-align:center}' +
      // '.camera__container{padding:12px 15px;}' +
      'object{display:block;/*HTML5 fix*/position:relative;z-index:1000}' +
      '#camera{display:block;box-sizing:content-box;position:relative;width:320px;height:240px;margin:0 auto;border:20px solid #333;background:#eee;-webkit-border-radius: 20px;-moz-border-radius:20px;border-radius:20px}' +
      '#canvas{display:none;box-sizing:content-box;position:absolute;z-index:4999;background-color:transparent}' +
      '#device{position:absolute;z-index:5001;padding-left:3px;color:#eee;font-size:12px}' +
      '#flash{display:none;position:absolute;z-index:5000;width:320px;height:240px;background-color:#c00}' +
      '#remain>span{font-size:15px;font-weight:700;font-family:Consolas, "Courier New", "Microsoft YaHei", SimHei}';
    styleNode.id = 'camera__style';
    styleNode.type = 'text/css';
    if (styleNode.styleSheet) {
      styleNode.styleSheet.cssText = cssString;
    } else {
      styleNode.innerHTML = cssString; // styleNode.appendChild(document.createTextNode(cssString))
    }
    document.getElementsByTagName('head')[0].appendChild(styleNode);
  }

  function base64() {
    if (window.atob) {
      return;
    } else {
      var Base64 = window.Base64 || {
        /* private property*/
        _keyStr: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',

        /* public method for encoding */
        encode: function(input) {
          var output = '';
          var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
          var i = 0;

          input = Base64._utf8_encode(input);

          while (i < input.length) {
            chr1 = input.charCodeAt(i++);
            chr2 = input.charCodeAt(i++);
            chr3 = input.charCodeAt(i++);

            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;

            if (isNaN(chr2)) {
              enc3 = enc4 = 64;
            } else if (isNaN(chr3)) {
              enc4 = 64;
            }

            output = output +
              Base64._keyStr.charAt(enc1) + Base64._keyStr.charAt(enc2) +
              Base64._keyStr.charAt(enc3) + Base64._keyStr.charAt(enc4);
          }

          return output;
        },

        /* public method for decoding */
        decode: function(input) {
          var output = '';
          var chr1, chr2, chr3;
          var enc1, enc2, enc3, enc4;
          var i = 0;

          input = input.replace(/[^A-Za-z0-9\+\/\=]/g, '');

          while (i < input.length) {
            enc1 = Base64._keyStr.indexOf(input.charAt(i++));
            enc2 = Base64._keyStr.indexOf(input.charAt(i++));
            enc3 = Base64._keyStr.indexOf(input.charAt(i++));
            enc4 = Base64._keyStr.indexOf(input.charAt(i++));

            chr1 = (enc1 << 2) | (enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;

            output = output + String.fromCharCode(chr1);

            if (enc3 != 64) {
              output = output + String.fromCharCode(chr2);
            }
            if (enc4 != 64) {
              output = output + String.fromCharCode(chr3);
            }
          }

          output = Base64._utf8_decode(output);

          return output;
        },

        /* private method for UTF-8 encoding */
        _utf8_encode: function(string) {
          string = string.replace(/\r\n/g, '\n');
          var utftext = '';

          for (var n = 0; n < string.length; n++) {
            var c = string.charCodeAt(n);

            if (c < 128) {
              utftext += String.fromCharCode(c);
            } else if ((c > 127) && (c < 2048)) {
              utftext += String.fromCharCode((c >> 6) | 192);
              utftext += String.fromCharCode((c & 63) | 128);
            } else {
              utftext += String.fromCharCode((c >> 12) | 224);
              utftext += String.fromCharCode(((c >> 6) & 63) | 128);
              utftext += String.fromCharCode((c & 63) | 128);
            }
          }

          return utftext;
        },

        /* private method for UTF-8 decoding */
        _utf8_decode: function(utftext) {
          var string = '';
          var i = 0;
          var c = 0;
          // var c1 = 0;
          var c2 = 0;
          var c3 = 0;

          while (i < utftext.length) {
            c = utftext.charCodeAt(i);

            if (c < 128) {
              string += String.fromCharCode(c);
              i++;
            } else if ((c > 191) && (c < 224)) {
              c2 = utftext.charCodeAt(i + 1);
              string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
              i += 2;
            } else {
              c2 = utftext.charCodeAt(i + 1);
              c3 = utftext.charCodeAt(i + 2);
              string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
              i += 3;
            }
          }
          return string;
        }
      };
      window.Base64 = Base64;
    }
  }

  camera.init = function() {
    setCss();
    base64();
  };

  camera.render = function(cb) {
    var that = this;

    that.init();
    vw.popup({
      title  : '拍照',
      area   : ['600px', '380px'],
      resize : false,
      id     : 'LAY-admin-camera',
      content: [
        '<div lay-module="camera" class="camera__container">',
        '  <div class="layui-row layui-col-space8">',
        '    <div class="layui-col-xs8">',
        '      <div id="camera">',
        '        <span id="device">设备</span>',
        '        <canvas id="canvas" width="320" height="240"></canvas>',
        '        <div id="flash"></div>',
        '      </div>',
        '    </div>',
        '    <div class="layui-col-xs4">',
        '      <div class="layui-row">',
        '        <label for="imgName">照片名</label>',
        '      </div>',
        '      <div class="layui-row">',
        '        <input id="imgName" type="text" class="layui-input" placeholder="请输入照片名">',
        '      </div>',
        '      <div class="layui-row" style="margin-top:30px;">',
        '        <button id="takePhoto" event="1" type="button" class="layui-btn layui-btn-normal layui-btn-fluid"><i class="layui-icon">&#xe660;</i> <span>拍照</span></button>',
        '      </div>',
        '      <div class="layui-row">',
        '        <button id="savePhoto" type="button" class="layui-btn layui-btn-normal layui-btn-fluid" disabled="true"><i class="layui-icon">&#xe610;</i> 提取</button>',
        '      </div>',
        '      <div class="layui-row" style="margin-top:20px;">',
        '        <span class="layui-hide" id="remain">剩余 <span>0</span> s</span>',
        '      </div>',
        '    </div>',
        '  </div>',
        '</div>'
      ].join(''),
      success: function(_, index) {
        var
          $scope    = $('[lay-module="camera"]');
        var $camera   = $scope.find('#camera');
        var $device   = $scope.find('#device');
        var $canvas   = $scope.find('#canvas');
        // var $flash    = $scope.find('#flash');
        var $remain   = $scope.find('#remain');
        var $inpImg   = $scope.find('#imgName');
        var $btnTake  = $scope.find('#takePhoto');
        var $btnSave  = $scope.find('#savePhoto');
        var
          canvas    = $canvas.get(0);
        var saveCb    = null;
        var ctx       = null;
        var image     = [];
        var pos       = 0;

        // Step1: 将输入框值填入
        $inpImg.val(defaultName);
        // Step2: 将参数处理完毕
        if (canvas.toDataURL) {
          ctx = canvas.getContext('2d');

          image = ctx.getImageData(0, 0, 320, 240);
          saveCb = function(data) {
            var
              col = data.split(';');
            var _image = image;

            for (var i = 0; i < 320; i++) {
              var item = parseInt(col[i]);

              _image.data[pos] = (item >> 16) & 0xff;
              _image.data[pos + 1] = (item >> 8) & 0xff;
              _image.data[pos + 2] = item & 0xff;
              _image.data[pos + 3] = 0xff;
              pos += 4;
            }

            if (pos >= 4 * 320 * 240) {
              ctx.putImageData(_image, 0, 0);
              var
                dataUrl  = canvas.toDataURL('image/png');
              var _arrData = dataUrl.split(',');
              var _strMime = _arrData[0].match(/:(.*?);/)[1];
              var _strBlob = atob(_arrData[1]);
              var _lenBlob = _strBlob.length;
              var _arrU8   = new Uint8Array(_lenBlob);
              // 这里需要转换成blob对象，因为所有的file都继承它
              while (_lenBlob--) {
                _arrU8[_lenBlob] = _strBlob.charCodeAt(_lenBlob);
              }

              that.imageInfo = {
                isCanvas: true,
                u8      : [_arrU8],
                mime    : _strMime
              };

              pos = 0;
            }
          };
        } else {
          image = [];
          saveCb = function(data) {
            image.push(data);
            pos += 4 * 320;
            if (pos >= 4 * 320 * 240) {
              that.imageInfo = {
                isCanvas: false,
                type    : 'pixel',
                img     : image.join('|'),
                width   : 320,
                height  : 240
              };
              // TODO 这里应该需要利用后台处理像素矩阵获取图片

              pos = 0;
              image = [];
            }
          };
        }
        // Step3: 初始化webcam组件
        $camera.webcam({
          width    : 320,
          height   : 240,
          mode     : 'callback',
          swffile  : $$path + '/lib/jquery-webcam/jscam.swf',
          onSave   : saveCb,
          onCapture: function() {
            webcam.save();
          },
          onTick: function(remain) {
            $remain.css('display', 'inline');
            $remain.find('span').text(remain);
            if (remain === 0) {
              setTimeout(function() {
                $remain.text('拍照成功');
                $canvas.css('display', 'block');
                $btnTake.find('span').text('重拍');
                $btnTake.removeAttr('disabled');
                $btnSave.removeAttr('disabled');
              }, 1200);
            }
          },
          onLoad: function() {
            var cams = webcam.getCameraList();
            cams.length && $device.text(cams[0]);
          }
        });
        // Step4: 绑定事件
        $btnTake.on('click', function(e) {
          var
            $this = $(this);
          var event = $this.attr('event');

          if (+event === 1) {
            $canvas.attr('allow', 'yes');
            $remain.removeClass('layui-hide');
            $btnSave.attr('disabled', true);
            $this.attr('event', 2);
            $this.attr('disabled', true);
            webcam.capture(2);
          } else {
            $canvas.attr('allow', 'no');
            $canvas.removeAttr('style');
            $remain.addClass('layui-hide');
            $remain.html('剩余 <span>0</span> s');
            $btnSave.attr('disabled', true);
            $this.attr('event', 1);
            $this.find('span').text('拍照');
          }
        });
        $btnSave.on('click', function(e) {
          var
            _fileName = $inpImg.val();
          var _imgInfo  = that.imageInfo;
          var outFile   = null;

          if (!isValidName(_fileName)) {
            ly.msg('照片名不能包含/ \\ : * ? \\" < > |, 并且不能以.开头');
            return false;
          }

          if ($canvas.attr('allow') === 'yes') {
            if (_imgInfo && _imgInfo.isCanvas) {
              // 无法兼容IE10以及IE10以下
              // outFile = new File(_imgInfo.u8, _fileName + defaultSuffix, {type: _imgInfo.mime})
              outFile = new Blob(_imgInfo.u8, { type: _imgInfo.mime });
            } else {
              ly.msg('暂时未兼容ie9，请更新更高的浏览器');
            }
          } else {
            outFile = _imgInfo;
          }

          if (isEmptyObject(outFile)) {
            ly.msg('当前文件信息输出失败');
            return false;
          }

          ly.alert('确定此张照片吗', function(idx) {
            ly.close(idx);
            typeof cb === 'function' && cb(outFile, _fileName + defaultSuffix, index);
          });
        });
      }
    });
  };

  e('camera', camera);
})
;
